﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSE.Framework.Process;
using PSE.Hosting.ServiceHoster.Business.Services;
using PSE.Hosting.ServiceHoster.Logging;

namespace PSE.Hosting.ServiceHoster.Business.Processes
{
    public class ServiceHosterPackageProcess : HierarchicalProcess<IServiceHosterPackageService>
    {
        protected override Uri GetServiceAddress()
        {
            return new Uri(string.Format("net.pipe://localhost/ServiceHosterPackageService/{0}", this.Name));
        }

        protected override void OnRestarted(EventArgs e)
        {
            base.OnRestarted(e);

            this.StartAll(true);
        }

        protected override void OnCheckIsAliveException(ProcessExceptionEventArgs e)
        {
            base.OnCheckIsAliveException(e);

            Logger.Log(new Exception(string.Format("Unable to restart the process '{0}'", e.Process.Name), e.Exception), Logger.EntryType.Error);

            e.Handled = true;
        }

        #region Proxy Methods

        /// <summary>
        /// Start all services a specified package.
        /// </summary>
        /// <param name="packageName">The package name to start the services.</param>
        public List<MessageData> StartAll(bool initialize)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                return proxy.GetInstance().StartAll(initialize);
            }
        }

        /// <summary>
        /// Stop all the services from an assembly.
        /// </summary>
        /// <param name="packageName">The name of the package containing the assembly to be stopped.</param>
        /// <param name="codeBase">The name of the assembly to be stopped.</param>
        public void StopAssembly(string codeBase)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                proxy.GetInstance().StopAssembly(codeBase);
            }
        }

        /// <summary>
        /// Start all WCF services from a specific assembly.
        /// </summary>
        /// <param name="packageName">The name of the package of the assembly to start.</param>
        /// <param name="fileName">The name of the assembly file to start. This is the filename only, without the path.</param>
        /// 
        public List<MessageData> StartAssembly(string fileName)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                return proxy.GetInstance().StartAssembly(fileName);
            }
        }

        /// <summary>
        /// Starts a Service configured within the Hoster app.config.
        /// </summary>
        /// <param name="assembly">The assembly name.</param>
        /// <param name="serviceName">The service name to start.</param>
        public void StartService(string assembly, string serviceName)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                proxy.GetInstance().StartService(assembly, serviceName);
            }
        }

        /// <summary>
        /// Stops the specified service.
        /// </summary>
        /// <param name="packageName">The name of the package containing the service.</param>
        /// <param name="assembly">The assembly name.</param>
        /// <param name="serviceName">The service name to stop.</param>
        public void StopService(string assembly, string serviceName)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                proxy.GetInstance().StopService(assembly, serviceName);
            }
        }

        /// <summary>
        /// Stops all the services already started from a specific package.
        /// </summary>
        public void StopAll()
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                proxy.GetInstance().StopAll();
            }
        }

        /// <summary>
        /// Gets a list of all the services configured within the Service Hoster app.config.
        /// </summary>
        /// <returns></returns>
        public List<Entities.Service> GetServiceList(string assembly)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                return proxy.GetInstance().GetServiceList(assembly);
            }
        }

        /// <summary>
        /// Returns a list of all the assemblies added in a package.
        /// </summary>
        /// <param name="packageName">The name of the package to get the list of assenblies.</param>
        /// <returns>List of added assemblies.</returns>
        public List<Entities.Assembly> GetAssemblyList()
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                return proxy.GetInstance().GetAssemblyList();
            }
        }

        /// <summary>
        /// Adds a Service to the Service Hoster config file.
        /// </summary>
        /// <param name="packageName">The name of the package.</param>
        /// <param name="codeBase">The assembly code base.</param>
        /// <param name="domain">The domain name of the user.</param>
        /// <param name="userName">The user name for impersonate service operations.</param>
        /// <param name="password">The user password.</param>
        public void AddAssembly(string codeBase)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                proxy.GetInstance().AddAssembly(codeBase);
            }
        }

        /// <summary>
        /// Removes a Service from the Service Hoster config file.
        /// </summary>
        /// <param name="packageName">The name of the package.</param>
        /// <param name="assemblyFile">The name of the assembly file (without path).</param>
        public void RemoveAssembly(string assemblyFile)
        {
            this.CheckIsDisposed();

            using (ProcessServiceProxy<IServiceHosterPackageService> proxy = new ProcessServiceProxy<IServiceHosterPackageService>(this.GetServiceAddress()))
            {
                proxy.GetInstance().RemoveAssembly(assemblyFile);
            }
        }
        #endregion
    }
}
